package com.qyb.base.java8.chap5;


import com.qyb.base.java8.bean.Dish;

import java.util.Arrays;
import java.util.List;
import java.util.Optional;

import static com.qyb.base.java8.bean.Dish.menu;

/*
    allMatch、anyMatch、noneMatch: 短路求值,不需要处理整个流就能得到结果。
    findFirst和findAny

     Optional<T>类（java.util.Optional）是一个容器类，代表一个值存在或不存在。在
     代码中，findAny可能什么元素都没找到。

    Optional里面几种可以迫使你显式地检查值是否存在或处理值不存在的情形的方法也不错。
         isPresent()将在Optional包含值的时候返回true, 否则返回false。
         ifPresent(Consumer<T> block)会在值存在的时候执行给定的代码块。我们在第3章
                介绍了Consumer函数式接口；它让你传递一个接收T类型参数，并返回void的Lambda
                表达式。
         T get()会在值存在时返回值，否则抛出一个NoSuchElement异常。
         T orElse(T other)会在值存在时返回值，否则返回一个默认值。

 */
public class Finding{

    public static void demo1(){
        if(isVegetarianFriendlyMenu()){
            System.out.println("Vegetarian friendly");
        }

        System.out.println(isHealthyMenu());
        System.out.println(isHealthyMenu2());
        
        Optional<Dish> dish = findVegetarianDish();
        dish.ifPresent(d -> System.out.println(d.getName()));

        testFindFirst();
    }
    
    private static boolean isVegetarianFriendlyMenu(){
        // 检查谓词是否至少匹配一个元素,:“流中是否有一个元素能匹配给定的谓词”。
        // anyMatch方法返回一个boolean，因此是一个终端操作。
        return menu.stream().anyMatch(Dish::isVegetarian);
    }
    
    private static boolean isHealthyMenu(){
        // 检查谓词是否匹配所有元素:流中的元素是否都能匹配给定的谓词.
        return menu.stream().allMatch(d -> d.getCalories() < 1000);
    }
    
    private static boolean isHealthyMenu2(){
        //流中没有任何元素与给定的谓词匹配。
        return menu.stream().noneMatch(d -> d.getCalories() >= 1000);
    }
    
    private static Optional<Dish> findVegetarianDish(){
        //查找元素:findAny 利用短路找到结果时立即结束。

        return menu.stream().filter(Dish::isVegetarian).findAny();
    }

    private static void testFindFirst(){
        //查找第一个元素
        List<Integer> someNumbers = Arrays.asList(1, 2, 3, 4, 5);
        Integer firstSquareDivisibleByThree =
                someNumbers.stream()
                        .map(x -> x * x)
                        .filter(x -> x % 3 == 0)
                        .findFirst().orElse(null); // 9
    }
    
}
